﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Security;
using System.Text.RegularExpressions;

namespace Infrastructure.Common.Log.Imp
{
    public sealed class TraceSourceLog
        : ILogger
    {
        #region Members

        private readonly string LogPath;
        private readonly TraceSource _source;
        private readonly string switchLevel = SourceLevels.Error.ToString();
        private int dayLength = 2;

        #endregion

        #region  Constructor

        /// <summary>
        ///     Create a new instance of this trace manager
        /// </summary>
        public TraceSourceLog(string logPath)
        {
            // Create default source
            LogPath = logPath;
            _source = new TraceSource("NLayerApp");
            //source = new TraceSource("WindowsApplication1", SourceLevels.Verbose);//SourceLevels调高调低根据消息级别控制日志输出,强制SourceLevels.Verbose全部输出
        }

        #endregion

        #region Private Methods

        /// <summary>
        ///     Trace internal message in configured listeners
        /// </summary>
        /// <param name="eventType">Event type to trace</param>
        /// <param name="message">Message of event</param>
        private void TraceInternal(TraceEventType eventType, string message)
        {
            if (_source != null)
            {
                try
                {
                    _source.Switch = new SourceSwitch("sourceSwitch", switchLevel);

                    //写入输出
                    /* TextWriterTraceListener myTextListener = new TextWriterTraceListener();
                    source.Listeners.Add(myTextListener);
                    source.TraceEvent(eventType, (int)eventType, DateWraper(message));
                    */
                    //写入输出和日志
                    Stream myFile = File.Open(LogPath, FileMode.Append);
                    var myTextListener = new TextWriterTraceListener(myFile);
                    // myTextListener.TraceOutputOptions = TraceOptions.None;
                    _source.Listeners.Add(myTextListener);
                    _source.TraceEvent(eventType, (int) eventType, DateWraper(message));
                    _source.Flush();
                    _source.Close();

                    RetrieveFileToDay(dayLength);
                }
                catch (SecurityException)
                {
                    //Cannot access to file listener or cannot have
                    //privileges to write in event log etc...
                }
            }
        }


        /*  public void setSwitch(string leve)
        {
            source.Switch = new SourceSwitch("sourceSwitch", leve);
        }*/

        #endregion

        #region ILogger Members

        public void LogInfo(string message, params object[] args)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {
                string messageToTrace = string.Format(CultureInfo.InvariantCulture, message, args);

                TraceInternal(TraceEventType.Information, messageToTrace);
            }
        }

        public void LogWarning(string message, params object[] args)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {
                string messageToTrace = string.Format(CultureInfo.InvariantCulture, message, args);

                TraceInternal(TraceEventType.Warning, messageToTrace);
            }
        }


        public void LogError(string message, params object[] args)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {
                string messageToTrace = string.Format(CultureInfo.InvariantCulture, message, args);

                TraceInternal(TraceEventType.Error, messageToTrace);
            }
        }


        public void LogError(string message, Exception exception, params object[] args)
        {
            if (!String.IsNullOrWhiteSpace(message)
                &&
                exception != null)
            {
                string messageToTrace = string.Format(CultureInfo.InvariantCulture, message, args);

                string exceptionData = exception.ToString();
                // The ToString() create a string representation of the current exception

                TraceInternal(TraceEventType.Error,
                    string.Format(CultureInfo.InvariantCulture, "{0} Exception:{1}", messageToTrace, exceptionData));
            }
        }


        public void Debug(string message, params object[] args)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {
                string messageToTrace = string.Format(CultureInfo.InvariantCulture, message, args);

                TraceInternal(TraceEventType.Verbose, messageToTrace);
            }
        }


        public void Debug(string message, Exception exception, params object[] args)
        {
            if (!String.IsNullOrWhiteSpace(message)
                &&
                exception != null)
            {
                string messageToTrace = string.Format(CultureInfo.InvariantCulture, message, args);

                string exceptionData = exception.ToString();
                // The ToString() create a string representation of the current exception

                TraceInternal(TraceEventType.Error,
                    string.Format(CultureInfo.InvariantCulture, "{0} Exception:{1}", messageToTrace, exceptionData));
            }
        }


        public void Debug(object item)
        {
            if (item != null)
            {
                TraceInternal(TraceEventType.Verbose, item.ToString());
            }
        }


        public void Fatal(string message, params object[] args)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {
                string messageToTrace = string.Format(CultureInfo.InvariantCulture, message, args);

                TraceInternal(TraceEventType.Critical, messageToTrace);
            }
        }

        public void Fatal(string message, Exception exception, params object[] args)
        {
            if (!String.IsNullOrWhiteSpace(message)
                &&
                exception != null)
            {
                string messageToTrace = string.Format(CultureInfo.InvariantCulture, message, args);

                string exceptionData = exception.ToString();
                // The ToString() create a string representation of the current exception

                TraceInternal(TraceEventType.Critical,
                    string.Format(CultureInfo.InvariantCulture, "{0} Exception:{1}", messageToTrace, exceptionData));
            }
        }

        #endregion

        #region ILogger Private Members 3.29提交

        private string DateWraper(string message)
        {
            string compmess = string.Format("{0} {1} ", message, DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss"));

            return compmess;
        }


        /// <summary>
        ///     截取日志到近几天
        /// </summary>
        /// <param name="dayLen"></param>
        public void RetrieveFileToDay(int dayLen)
        {
            string toDay = GetToDate(dayLen);

            try
            {
                string[] ss = File.ReadAllLines(@LogPath);
                var targetArr = new string[ss.Length];
                for (int i = 0; i < ss.Length; i++)
                {
                    string reg = @"\d{4}-\d{1,2}-\d{2}";
                    var r = new Regex(reg);
                    MatchCollection mc;
                    mc = r.Matches(ss[i]);

                    //  截取日期大于日志记录日期的日志

                    if (mc.Count > 0 && String.Compare(mc[0].Value, toDay, StringComparison.Ordinal) >= 0)
                    {
                        Array.Copy(ss, i, targetArr, 0, ss.Length - i);
                        File.WriteAllLines(@LogPath, targetArr);
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                throw (new Exception("截取写入日志错误!!!" + ex.Message));
            }
        }

        /// <summary>
        ///     取得近几天日期
        /// </summary>
        /// <param name="dayLength">取得到今天日志最近几天</param>
        /// <returns></returns>
        private static string GetToDate(int dayLength)
        {
            DateTime dt = DateTime.Now;
            dt = dt.AddDays(-dayLength);
            string time = dt.ToString("yyyy-MM-dd");
            return time;
        }

        #endregion
    }
}